package com.cib.xagcjs.config;

import com.alibaba.fastjson.JSONObject;
import com.cib.xagcjs.biz.*;
import com.cib.xagcjs.common.EcnyLockRequest;
import com.cib.xagcjs.common.EcnyUnlockRequest;
import com.cib.xagcjs.common.EcnytPaymentRequest;
import com.cib.xagcjs.common.RmbRequest;
import com.cib.xagcjs.dto.PaymentResult;
import com.cib.xagcjs.utils.CryptoUtils;
import com.cib.xagcjs.utils.RequestUtil;
import com.cib.xagcjs.utils.TimeUtil;
import com.cib.xagcjs.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Description: 定时任务处理
 * Author: jingcaiqi1225@gmail.com
 * Date: 2024/2/4 11:25
 */
@Slf4j
@Component
public class TaskConfig {

    @Autowired
    private RequestUtil requestUtil;

    @Autowired
    private PaymentNotifyService paymentNotifyService;

    @Autowired
    private PayContentService payContentService;

    @Autowired
    private EcnyPaymentNotifyService ecnyPaymentNotifyService;

    @Autowired
    private EcnyLockService ecnyLockService;

    @Autowired
    private EcnyUnLockService ecnyUnLockService;

    @Autowired
    private MessageLogService messageLogService;

    @Autowired
    private CryptoUtils cryptoUtils;


    /**
     * 执行人民币支付结果轮巡回传任务
     * @return 发送结果 ok 成功 false 失败
     */
    public String sendResult() {

        // 此处为轮巡代码
        // 查询通知表状态已更改为 3 支付完成的批次号数组
        // 拿到这个批次号查询这个批次下是否所有数据成功入账，
        // 将这个详情列表加密组装发送给区块链
        // 修改通知表状态为 4 已反馈
        String[] batches = paymentNotifyService.selectBatches(3);
        if (batches != null) {
            for (String batch : batches) {
                // 查询该批次下所有数据是否入账成功
                // 查询当前批次入库时记录的总笔数
                int totalNum = paymentNotifyService.selectTotalNum(batch);
                // 获取这个批次已处理的列表信息
                List<PayContent> list = payContentService.selectList(batch);
                // 组装报文发送区块链
                if (totalNum == list.size()) {
                    // 此处负责组装报文并给区块链发送处理结果
                    ArrayList<Object> args = new ArrayList<>();

                    // 根据batch获取当前批次的主表通知信息
                    PaymentNotify paymentNotify = paymentNotifyService.selectPayNotify(batch);
                    for (PayContent payContent : list) {
                        // 创建支付结果回传对象
                        PaymentResult paymentResult = new PaymentResult();
                        // 所属银行
                        paymentResult.setBank(paymentNotify.getBank());
                        //
                        paymentResult.setInstId(UUID.randomUUID().toString());
                        // 返回结果种类
                        paymentResult.setOptype("1");
                        // 支付结果细表类提取
                        PaymentResult.PaymentResultDto dto = PaymentResult.getPaymentResultDto(payContent);
                        // 整合报文
                        paymentResult.setContent(dto);
                        args.add(paymentResult);
                    }
                    // 最后组装
                    RmbRequest request = requestUtil.getRequest("pay/notify",args);
                    log.info("查看组装的报文请求：" + request);
                    // 转换为JSON格式
                    log.info("JSON格式打印：" + JSONObject.toJSONString(request));

//                         模拟消息回传给区块链1
//                         RestTemplate restTemplate = new RestTemplate();
//                         restTemplate.getForEntity("https://localhost:8080/hello", String.class);

                    messageLogService.insertMessageLog(1, "支付结果回传", TimeUtil.getNowTime(), JSONObject.toJSONString(request));
                }

                // 修改通知表状态为 4 已反馈
                paymentNotifyService.updateStatus(batch, 4);
            }
        }
        return "OK";
    }

    /**
     * 查询通知为 2 以获取支付详情的批次，校验该批次数据是否处理完毕，处理的数据将状态更改为 3 已支付（30秒执行一次）
     * @return 执行结果 OK" 成功 FALSE 失败
     */
    public String updateNotify() {
        // 定义计数器
        int key = 0;
        // 查询通知表状态已更改为 2 以获取支付详情的批次
        String[] batches = paymentNotifyService.selectBatches(2);
        // 拿到这个批次号查询这个批次下是否所有数据成功入账，
        for (String batch : batches) {
            // 查询该批次下所有数据是否入账成功
            // 查询当前批次入库时记录的总笔数
            int totalNum = paymentNotifyService.selectTotalNum(batch);
            // 获取这个批次已处理的列表信息
            List<PayContent> list = payContentService.selectList(batch);
            if (totalNum == list.size()) {
                // 修改通知表状态为 3 已支付
                paymentNotifyService.updateStatus(batch, 3);
                log.info("批次号为：{} 的批次下数据已全部入账", batch);
            } else {
                key++;
                log.info("批次号为：{} 的批次下数据未全部入账", batch);
            }
        }
        if (key == 0) {
            return "OK";
        } else {
            return "FALSE";
        }
    }

    /**
     * 执行数币支付结果回传
     * @return 发送结果 ok 成功 false 失败
     */
    public String sendEcnyResult() {
        // 获取数币主表支付状态已经更改为 2 已支付 的列表
        List<EcnyPaymentVO> ecnyPaymentVOS = ecnyPaymentNotifyService.selectByTransId(2);
        // 轮巡transId
        for (EcnyPaymentVO ecnyPaymentVO  : ecnyPaymentVOS) {
            // 根据这个批次的transId 获取下面所有 状态 1-付款成功，收款已确认 的列表
            List<EcnyPaymentListVO> list = ecnyPaymentNotifyService.selectList(ecnyPaymentVO.getTransId());
            // 组装报文发送区块链
            if (ecnyPaymentVO.getTotalCount() == list.size()) {
                // 此处负责组装报文并给区块链发送处理结果
                EcnytPaymentRequest request = getEcnytPaymentRequest(ecnyPaymentVO, list);
                log.info("查看组装的报文请求：" + request);
                // 转换为JSON格式
                log.info("JSON格式打印：" + JSONObject.toJSONString(request));
//                  模拟消息发送给前置
//                  RestTemplate restTemplate = new RestTemplate();
//                  restTemplate.getForEntity("https://localhost:8080/hello", String.class);
                messageLogService.insertMessageLog(1, "数币支付结果回传", TimeUtil.getNowTime(), JSONObject.toJSONString(request));
            } else {
                log.info("交易唯一号为：{} 的批次下数据未全部入账", ecnyPaymentVO.getTransId());
            }
            // 修改通知表状态为 3 已反馈
            ecnyPaymentNotifyService.updateStatus(ecnyPaymentVO.getTransId(), 3);
        }
        return "OK";
    }

    /**
     * 执行数币冻结结果通知
     * @return 发送结果 OK 成功 FALSE 失败
     */
    public String sendEcnyLockResult() {
        // 获取冻结主表冻结状态已经更改为 2 已冻结 列表
        List<EcnyLockVO> ecnyLockVOS = ecnyLockService.selectLock(2);
        // 轮巡
        for (EcnyLockVO ecnyLockVO  : ecnyLockVOS) {
            // 根据这个批次的transId 获取下面所有 状态 1-成功 的列表
            List<EcnyLockListVO> list = ecnyLockService.selectLockList(ecnyLockVO.getTransId(), 1);
            // 组装报文发送区块链
            if (ecnyLockVO.getTotalLockCount() == list.size()) {
                // 此处负责组装报文并给区块链发送处理结果
                EcnyLockRequest request = getEcnyLockRequest(ecnyLockVO, list);
                log.info("查看组装的报文请求：" + request);
                // 转换为JSON格式
                log.info("JSON格式打印：" + JSONObject.toJSONString(request));
//                  模拟消息发送给前置
//                  RestTemplate restTemplate = new RestTemplate();
//                  restTemplate.getForEntity("https://localhost:8080/hello", String.class);
                messageLogService.insertMessageLog(1, "数币冻结结果回传", TimeUtil.getNowTime(), JSONObject.toJSONString(request));
            } else {
                log.info("交易唯一号为：{} 的批次下数据未全部冻结", ecnyLockVO.getTransId());
                return "FALSE";
            }
            // 修改冻结通知表状态为 3 已反馈
            ecnyLockService.updateLockStatus(ecnyLockVO.getTransId(), 3);
        }
        return "OK";
    }

    /**
     * 执行数币解冻结果通知
     * @return 发送结果 OK 成功 FALSE 失败
     */
    public String sendEcnyUnLockResult() {
        // 获取解冻主表解冻状态已经更改为 2 已解冻 列表
        List<EcnyUnlockVO> ecnyUnlockVOS = ecnyUnLockService.selectUnLock(2);
        // 轮巡
        for (EcnyUnlockVO ecnyUnlockVO  : ecnyUnlockVOS) {
            // 根据这个批次的transId 获取下面所有 状态 1-成功 的列表
            List<EcnyLockListVO> list = ecnyUnLockService.selectUnLockList(ecnyUnlockVO.getTransId(), 1);
            // 组装报文发送区块链
            if (ecnyUnlockVO.getTotalUnlockCount() == list.size()) {
                // 此处负责组装报文并给区块链发送处理结果
                EcnyUnlockRequest request = getEcnyUnlockRequest(ecnyUnlockVO, list);
                log.info("查看组装的报文请求：" + request);
                // 转换为JSON格式
                log.info("JSON格式打印：" + JSONObject.toJSONString(request));
//                  模拟消息发送给前置
//                  RestTemplate restTemplate = new RestTemplate();
//                  restTemplate.getForEntity("https://localhost:8080/hello", String.class);
                messageLogService.insertMessageLog(1, "数币解冻结果回传", TimeUtil.getNowTime(), JSONObject.toJSONString(request));
            } else {
                log.info("交易唯一号为：{} 的批次下数据未全部解冻", ecnyUnlockVO.getTransId());
                return "FALSE";
            }
            // 修改冻结通知表状态为 3 已反馈
            ecnyUnLockService.updateUnLockStatus(ecnyUnlockVO.getTransId(), 3);
        }
        return "OK";
    }

    /**
     * 根据 EcnyUnlockVO 和 EcnyLockListVO 列表生成 EcnyUnlockRequest 对象。
     *
     * @param ecnyUnlockVO 包含交易 ID 的 EcnyUnlockVO 对象
     * @param list         包含解锁信息的 EcnyLockListVO 列表
     * @return 生成的 EcnyUnlockRequest 对象
     */
    private static EcnyUnlockRequest getEcnyUnlockRequest(EcnyUnlockVO ecnyUnlockVO, List<EcnyLockListVO> list) {
        // 创建 EcnyUnlockRequest 对象
        EcnyUnlockRequest request = new EcnyUnlockRequest();

        // 设置交易 ID
        request.setTransId(ecnyUnlockVO.getTransId());

        // 创建资产解锁列表
        List<EcnyUnlockRequest.AssetUnlock> assetUnlocks = new ArrayList<>();

        // 遍历解锁信息列表
        for (EcnyLockListVO ecnyLockListVO : list) {
            // 创建资产解锁对象
            EcnyUnlockRequest.AssetUnlock assetUnlock = new EcnyUnlockRequest.AssetUnlock();

            // 设置解锁指令 ID
            assetUnlock.setUnlockInstructId(ecnyLockListVO.getLockInstructId());

            // 设置解锁状态
            assetUnlock.setUnlockStatus(ecnyLockListVO.getStatus());

            // 设置解锁金额
            assetUnlock.setUnlockAmt(ecnyLockListVO.getLockAmt());

            // 设置解锁状态描述（暂为空字符串）
            assetUnlock.setUnlockStatusDesc("");

            // 将资产解锁对象添加到资产解锁列表
            assetUnlocks.add(assetUnlock);
        }

        // 设置资产解锁列表到请求对象中
        request.setAssetUnlockList(assetUnlocks);

        // 返回生成的请求对象
        return request;
    }


    /**
     * 根据 EcnyLockVO 和 EcnyLockListVO 列表生成 EcnyLockRequest 对象。
     *
     * @param ecnyLockVO 包含交易 ID 的 EcnyLockVO 对象
     * @param list       包含锁定信息的 EcnyLockListVO 列表
     * @return 生成的 EcnyLockRequest 对象
     */
    private static EcnyLockRequest getEcnyLockRequest(EcnyLockVO ecnyLockVO, List<EcnyLockListVO> list) {
        // 创建 EcnyLockRequest 对象
        EcnyLockRequest request = new EcnyLockRequest();

        // 设置交易 ID
        request.setTransId(ecnyLockVO.getTransId());

        // 创建资产锁定列表
        List<EcnyLockRequest.AssetLock> assetLockList = new ArrayList<>();

        // 遍历锁定信息列表
        for (EcnyLockListVO ecnyLockListVO : list) {
            // 创建资产锁定对象
            EcnyLockRequest.AssetLock lock = new EcnyLockRequest.AssetLock();

            // 设置锁定金额
            lock.setLockAmt(ecnyLockListVO.getLockAmt());

            // 设置锁定指令 ID
            lock.setLockInstructId(ecnyLockListVO.getLockInstructId());

            // 设置锁定状态
            lock.setLockStatus(ecnyLockListVO.getStatus());

            // 设置锁定状态描述（暂为空字符串）
            lock.setLockStatusDesc("");

            // 将资产锁定对象添加到资产锁定列表
            assetLockList.add(lock);
        }

        // 设置资产锁定列表到请求对象中
        request.setAssetLockList(assetLockList);

        // 返回生成的请求对象
        return request;
    }


    /**
     * 根据 主表对象 和 细表对象 生成 EcnytPaymentRequest 对象。
     *
     * @param ecnyPaymentVO 包含交易 ID 的 EcnyPaymentVO 对象
     * @param list          包含支付信息的 EcnyPaymentListVO 列表
     * @return 生成的 EcnytPaymentRequest 对象
     */
    private static EcnytPaymentRequest getEcnytPaymentRequest(EcnyPaymentVO ecnyPaymentVO, List<EcnyPaymentListVO> list) {
        // 创建 EcnytPaymentRequest 对象
        EcnytPaymentRequest request = new EcnytPaymentRequest();

        // 设置交易 ID
        request.setTransId(ecnyPaymentVO.getTransId());

        // 创建支付合同列表
        List<EcnytPaymentRequest.ContractPayment> contractPayments = new ArrayList<>();

        // 遍历支付信息列表
        for (EcnyPaymentListVO paymentListVO : list) {
            // 创建合同支付对象
            EcnytPaymentRequest.ContractPayment contractPayment = new EcnytPaymentRequest.ContractPayment();

            // 设置支付指令 ID
            contractPayment.setPayInstructId(paymentListVO.getPayInstructId());

            // 设置支付状态
            contractPayment.setPayStatus(paymentListVO.getStatus());

            // 设置支付金额
            contractPayment.setToAmt(paymentListVO.getToAmt());

            // 设置锁定金额
            contractPayment.setToLockAmt(paymentListVO.getToLockAmt());

            // 设置支付状态描述（暂为空字符串）
            contractPayment.setPayStatusDesc("");

            // 将合同支付对象添加到合同支付列表
            contractPayments.add(contractPayment);
        }

        // 设置合同支付列表到请求对象中
        request.setContractPayList(contractPayments);

        // 返回生成的请求对象
        return request;
    }
}